#ifndef __DYNARRAY_H__
#define __DYNARRAY_H__
#include <base.h>
namespace mdk
{
    template <class T>
    class dynArray
    {
    private:
#define INITIALCAPACITY 16
        enum BufType
        {
            FREAM_BUFFER,
            MALLOC_BUFFER
        };
        T **m_data;
        T *m_data_s[INITIALCAPACITY];
        BufType m_type;
        int m_count;
        int m_index;

    private:
        bool GetMoreCapacity(int len)
        {
            if (m_count >= len)
                return true;
            T **tmp = new T *[m_count += m_count >> 1];
            if (tmp == nullptr)
            {
                return false;
            }
            std::copy(m_data, m_data + m_index, tmp);
            if (MALLOC_BUFFER == m_type)
            {
                delete[] m_data;
            }
            m_type = MALLOC_BUFFER;
            m_data = tmp;
            return true;
        }
        void _init()
        {
            memset(m_data_s, 0, INITIALCAPACITY);
            m_data = m_data_s;
            m_type = FREAM_BUFFER;
            m_count = INITIALCAPACITY;
        }
        inline int makeArrayMask(int i) { return (i <= 0) ? 0 : ((Size() <= i) ? (Size() - 1) : --i); }

    public:
        dynArray() { _init(); }

        dynArray(int size)
        {
            _init();
            m_data = new T *[size];
            m_type = MALLOC_BUFFER;
            m_count = size;
        }

        ~dynArray()
        {
            for (int i = 0; i < m_index; i++)
            {
                delete m_data[i];
            }
            if (MALLOC_BUFFER == m_type)
            {
                delete[] m_data;
            }
            m_data = nullptr;
            memset(m_data_s, 0xbe, INITIALCAPACITY);
        }

        int Add(T *v)
        {
            (void)GetMoreCapacity(m_index + 1);
            m_data[m_index] = v;
            return m_index++;
        }

        inline int Add(T &v) { return Add(new T(v)); }

        int Add(int index, T *v)
        {
            if (index >= m_index || index < 0)
                return -1;
            (void)GetMoreCapacity(m_index + 1);
            std::copy(m_data + index, m_data + m_index, m_data + index + 1);
            m_data[index] = v;
            return m_index++;
        }

        int Add(int index, T &v)
        {
            if (index >= m_index || index < 0)
                return -1;
            (void)GetMoreCapacity(m_index + 1);
            std::copy(m_data + index, m_data + m_index, m_data + index + 1);
            m_data[index] = new T(v);
            return m_index++;
        }
        void remove(int index)
        {
            index = makeArrayMask(index);
            if (m_data[index] != nullptr)
            {
                delete m_data[index];
            }
            m_data[index] = nullptr;
            if (index > 0)
            {
                --m_index;
            }
            else
            {
                m_index = 0;
            }
            std::copy(m_data + index + 1, m_data + m_index + 1, m_data + index);
        }
        inline T *Get(int index) { return m_data[makeArrayMask(index)]; }
        inline int Size() { return m_index; }
        inline T *operator[](int index) { return m_data[makeArrayMask(index)]; }
    };
}
#endif